package cn.ccccltd.waf.message.base.consumer;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.jms.Message;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

import cn.ccccltd.waf.message.constant.MessageConstants;
import cn.ccccltd.waf.message.init.PropertyContext;
import cn.ccccltd.waf.message.model.vo.MessageSms;
import cn.ccccltd.waf.message.queue.log.constant.LogConstants;
import cn.ccccltd.waf.message.util.DateUtilsNew;
import cn.ccccltd.waf.message.util.JsonUtils;
import cn.ccccltd.waf.message.util.MessageUtils;
import cn.ccccltd.waf.message.util.QueueUtils;
import cn.ccccltd.waf.message.util.sql.SqlContext;

/**
 * 创建日期:2017年10月30日
 * Title:发送失败重试通用类
 * Description：消费者接口统一化
 * @author yangjingjiang
 * @mender：（文件的修改者，文件创建者之外的人）
 * @version 1.0
 * Remark：认为有必要的其他信息
 */
@Component
public abstract class BaseErrorConsumer {

	private static Logger log = LoggerFactory.getLogger(BaseErrorConsumer.class);
	
	@Resource(name="logJmsTemplate")
	private JmsTemplate logJmsTemplate;
	
	@Resource(name="errorJmsTemplate")
	private JmsTemplate jmsTemplate;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	
	
	/**
	 * 功能: 获取更新状态sql上下文<br>
	 * 作者: yangjingjiang <br>
	 * 创建日期:2017年11月13日 <br>
	 * 修改者: mender <br>
	 * 修改日期: modifydate <br>
	 * @param smsMessage
	 * @return
	 */
	protected abstract SqlContext getUpdateSqlContext(JSONObject smsMessage);
	
	/**
	 * 功能: 获取更新状态的JmsTemplate<br>
	 * 作者: yangjingjiang <br>
	 * 创建日期:2017年11月13日 <br>
	 * 修改者: mender <br>
	 * 修改日期: modifydate <br>
	 * @return
	 */
	protected abstract JmsTemplate getUpdateTableJmsTemplate();
	
	/**
	 * 功能: 发送消息并处理错误信息<br>
	 * 作者: yangjingjiang <br>
	 * 创建日期:2017年11月13日 <br>
	 * 修改者: mender <br>
	 * 修改日期: modifydate <br>
	 * @param smsMessage
	 * @return
	 */
	protected abstract Map<String,String> sendMessage(JSONObject smsMessage);
	
	/**
	 * 功能: 消费消息<br>
	 * 作者: yangjingjiang <br>
	 * 创建日期:2017年11月3日 <br>
	 * 修改者: mender <br>
	 * 修改日期: modifydate <br>
	 * @param message
	 */
	public void receiveMessage(Message message) {
		
		log.debug(MessageConstants.LOG_DEBUG_PREFIX + "接收到短信的错误信息,不处理错误次数+1！" + MessageUtils.getMessageText(message));
		
		JSONObject smsMessage = JsonUtils.toObject(MessageUtils.getMessageText(message), JSONObject.class);
		
		
		/** TODO
		 * 发送消息 根据第三方状态码校验发送成功失败  sendLogMap.get(LogConstants.LOG_REMOTE_CODE);
		 */
		Map<String, String> sendLogMap = sendMessage(smsMessage);
		String remoteCode = sendLogMap.get(LogConstants.LOG_REMOTE_CODE);
		//判断是否发送成功,第三方的发送成功
		boolean sendStatue = StringUtils.isNotBlank(remoteCode) && remoteCode.equals(HttpStatus.OK.toString());
		
		smsMessage.put(MessageConstants.SENDTIMES, smsMessage.getInteger(MessageConstants.SENDTIMES) + 1);
		//消息等级
		int msgScope = smsMessage.getInteger(MessageConstants.MSGSCOPE);
		//发送次数
		int sendTimes = smsMessage.getInteger(MessageConstants.SENDTIMES);
		//根据重要等级重试，此处初始发送次数为2
		if(sendTimes < msgScope + 3 && !sendStatue) {
			
			//获取更新sql
			SqlContext sqlContext = getUpdateSqlContext(smsMessage);
			String sql = sqlContext.getSql();
			
			try {
				jdbcTemplate.update(sql, sqlContext.getParams());
			} catch (DataAccessException e) {
				//更新数据库失败
				e.printStackTrace();
			}
			
			//设置延时后的发送时间
			Date date =  getSendDelay(msgScope + "", sendTimes);
			
			smsMessage.put(MessageConstants.SENDTIME, DateUtilsNew.formatDateTime(date));
			
			log.info(MessageConstants.LOG_DEBUG_PREFIX + DateUtilsNew.formatDateTime(date));

			Map<String, String> param = new HashMap<>(1);
			param.put(MessageConstants.SELECTOR, smsMessage.getString(MessageConstants.CATEGORY) + MessageConstants.ERROR_MESSAGE_SELECTOR);
			//重放回消息队列
			QueueUtils.sendMessageToQueue(jmsTemplate, smsMessage, param);

		}else if((!(sendTimes < msgScope + 3)) && !sendStatue) {
			
			smsMessage.put(MessageConstants.SENDSTATE, MessageConstants.SEND_FAIL);
			
			//让SmsUpdateTable队列更新发送失败状态
			QueueUtils.sendMessageToSmsUpdateTableQueue(getUpdateTableJmsTemplate(), smsMessage, MessageConstants.SEND_FAIL);
			
		}
		
		
		if(sendStatue){
			
			smsMessage.put(MessageConstants.SENDSTATE, MessageConstants.SEND_SUCCESS);
			smsMessage.put(MessageConstants.DELIVEREDTIME, DateUtilsNew.getDateTime());
			
			//让SmsUpdateTable队列更新发送状态
			QueueUtils.sendMessageToSmsUpdateTableQueue(getUpdateTableJmsTemplate(), smsMessage, MessageConstants.SEND_SUCCESS);
			
			
		}
		//发送发送消息的日志
		QueueUtils.sendMessageToQueue(logJmsTemplate, smsMessage,sendLogMap);
		
	}
	
	/**
	 * 功能: 设置最小延时时间<br>
	 * 作者: yangjingjiang <br>
	 * 创建日期:2017年11月8日 <br>
	 * 修改者: mender <br>
	 * 修改日期: modifydate <br>
	 * @param msgScope
	 * @param times
	 * @return
	 */
	private Date getSendDelay(String msgScope, Integer times) {
		
		String delayTime = PropertyContext.getProperty("error.delay.time");
		int unitTime = delayTime == null ? 10000 : Integer.valueOf(delayTime);
		long time =System.currentTimeMillis() +  unitTime * (10-Integer.valueOf(msgScope)) * (times-1);
		log.info(MessageConstants.LOG_DEBUG_PREFIX + "错误次数"+times+"==="+"延时时间为"+unitTime * (10-Integer.valueOf(msgScope)) * (times-1));
		return new Date(time);
		
	}
	
}
